import { GetAwsChunkedEncodingStream, GetAwsChunkedEncodingStreamOptions } from "@smithy/types";
import { buffer, stream } from "@kit.ArkTS";
import hilog from "@ohos.hilog";
import { PassThrough } from "./passThrough";

/**
 * @internal
 */
export const getAwsChunkedEncodingStream: GetAwsChunkedEncodingStream<stream.Readable> = (
  readableStream: stream.Readable,
  options: GetAwsChunkedEncodingStreamOptions
) => {
  return new AwsChunkedEncodingStream(readableStream,options)
};

const TAG = 'Aws_Chunked_Encoding_Stream'
export class AwsChunkedEncodingStream extends PassThrough{

  private checksumRequired:boolean=false
  private digest:Promise<Uint8Array>|undefined = undefined
  constructor(private readableStream: stream.Readable,private options: GetAwsChunkedEncodingStreamOptions) {
    super(readableStream,TAG);
    const { base64Encoder, bodyLengthChecker, checksumAlgorithmFn, checksumLocationName, streamHasher } = options;

    this.checksumRequired =
      base64Encoder !== undefined &&
        checksumAlgorithmFn !== undefined &&
        checksumLocationName !== undefined &&
        streamHasher !== undefined;
    this.digest = this.checksumRequired ? streamHasher!(checksumAlgorithmFn!, readableStream) : undefined;
    this.readableStream.pipe(this)
  }

  doPush(chunk: string | Uint8Array, encoding: string, callback: Function): void {
    const length = this.options.bodyLengthChecker(chunk) || 0;
    this.push(`${length.toString(16)}\r\n`);
    this.push(chunk);
    this.push("\r\n");
    callback();
  }

  async finally(): Promise<void> {
    this.push(`0\r\n`);
    if (this.checksumRequired) {
      const digestResult = await this.digest
      const checksum = this.options.base64Encoder(digestResult);
      this.push(`${this.options.checksumLocationName}:${checksum}\r\n`);
      this.push(`\r\n`);
    }
  }

}